/*
    共享智能指针shared_ptr
*/
#pragma once
#include <iostream>
#include <mutex>

namespace crawler
{
    template<class T>
    class shared_ptr
    {
    public:
        shared_ptr() : _ptr(nullptr), _cnt_ptr(nullptr)
        {}

        shared_ptr(T* ptr) :_ptr(ptr), _cnt_ptr(new int(1))
        {}

        shared_ptr(const shared_ptr<T>& sp)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _ptr = sp._ptr;
            _cnt_ptr = sp._cnt_ptr;
            (*_cnt_ptr)++;
        }

        shared_ptr<T>& operator=(const shared_ptr<T>& sp)
        {
            if(this != &sp)
            {
                std::unique_lock<std::mutex> lock(_mutex);
                if(_ptr && (--(*_cnt_ptr) == 0))
                    delete _ptr;
                _ptr = sp._ptr;
                _cnt_ptr = sp._cnt_ptr;
                (*_cnt_ptr)++;
            }
            return *this;
        }

        T& operator*()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            return *_ptr;
        }

        ~shared_ptr()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            if(_ptr && (--(*_cnt_ptr) == 0))
                delete _ptr;
        }

        T* operator->()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            return _ptr;
        }

    private:
        T* _ptr;
        int* _cnt_ptr;
        std::mutex _mutex;
    };
}